<template>
  <view class="stroke-page">
    <!-- 顶部标题区 -->
    <view class="page-title">笔画练习</view>
    
    <!-- 顶部进度区 -->
    <view class="progress-bar">
      <view class="stars">
        <image v-for="(star, index) in stars" 
               :key="index" 
               :src="'/static/images/star.png'"
               class="star-icon"/>
      </view>
      <text class="level-text">第 {{currentLevel}} 关</text>
    </view>
    
    <!-- 当前要写的字 -->
    <view class="current-char-container">
      <text class="current-char-text">{{currentLevelData.name}}</text>
    </view>
    
    <!-- 写字区域 -->
    <view class="writing-area">
      <!-- 参考线 -->
      <view class="guide-lines">
        <view class="guide-line horizontal"></view>
        <view class="guide-line vertical"></view>
      </view>
      
      <!-- 写字画布 -->
      <canvas 
        ref="writeCanvas"
        id="writeCanvas"
        class="write-canvas"
        @mousedown.prevent="handleMouseDown"
        @mousemove.prevent="handleMouseMove"
        @mouseup.prevent="handleMouseUp"
        @mouseleave.prevent="handleMouseUp"
        @touchstart.prevent="handleTouchStart"
        @touchmove.prevent="handleTouchMove"
        @touchend.prevent="handleTouchEnd"
      />
      
      <!-- 笔画示范动画 -->
      <view class="demo-stroke" v-if="showDemo">
        <view class="demo-line" :class="currentLevelData.name"></view>
      </view>
    </view>
    
    <!-- 底部按钮区 -->
    <view class="bottom-actions">
      <button class="action-btn demo-btn" @click="showStrokeDemo">
        看示范
      </button>
      <button class="action-btn clear-btn" @click="clearCanvas">
        重写
      </button>
      <button class="action-btn submit-btn" @click="checkStroke">
        完成
      </button>
    </view>
  </view>
</template>

<script lang="ts">
interface Point {
  x: number;
  y: number;
}

interface Particle extends Point {
  size: number;
  speedX: number;
  speedY: number;
  life: number;
}

interface StrokePattern {
  name: string;
  demoGif: string;
  validRange: {
    startX: [number, number];
    startY: [number, number];
    endX: [number, number];
    endY: [number, number];
    maxYDeviation: number;
  };
  sound: string;
}

interface CurrentStroke {
  name: string;
  demoGif: string;
  points: Point[];
}

interface UniTouchEvent {
  touches: {
    clientX: number;
    clientY: number;
  }[];
}

interface CanvasNode {
  width: number;
  height: number;
  getContext(contextId: string): CanvasRenderingContext2D;
  createImage(): HTMLImageElement;
}

interface BoundingClientRect {
  width: number;
  height: number;
  left: number;
  top: number;
}

// 添加关卡配置
const LEVELS = [
  {
    name: '横',
    pattern: 'horizontal',
    demoGif: '/static/strokes/horizontal.gif',
    sound: '/static/sounds/horizontal.mp3'
  },
  {
    name: '竖',
    pattern: 'vertical',
    demoGif: '/static/strokes/vertical.gif',
    sound: '/static/sounds/vertical.mp3'
  },
  {
    name: '撇',
    pattern: 'left-slash',
    demoGif: '/static/strokes/left-slash.gif',
    sound: '/static/sounds/left-slash.mp3'
  }
];

export default {
  data() {
    return {
      currentLevel: 1,
      stars: 0,
      showDemo: false,
      currentStroke: {
        name: '横',
        demoGif: '/static/strokes/horizontal.gif',
        points: []
      } as CurrentStroke,
      ctx: null as CanvasRenderingContext2D | null,
      particleCanvasCtx: null as CanvasRenderingContext2D | null,
      canvasNode: null as CanvasNode | null,
      strokePatterns: {
        horizontal: {
          name: '横',
          demoGif: '/static/strokes/horizontal.gif',
          validRange: {
            startX: [0.1, 0.3],
            startY: [0.4, 0.6],
            endX: [0.7, 0.9],
            endY: [0.4, 0.6],
            maxYDeviation: 0.1
          }
        },
        vertical: {
          name: '竖',
          demoGif: '/static/strokes/vertical.gif',
          validRange: {
            startX: [0.4, 0.6],
            startY: [0.1, 0.3],
            endX: [0.4, 0.6],
            endY: [0.7, 0.9],
            maxYDeviation: 0.1
          }
        },
        'left-slash': {
          name: '撇',
          demoGif: '/static/strokes/left-slash.gif',
          validRange: {
            startX: [0.6, 0.8],
            startY: [0.2, 0.4],
            endX: [0.2, 0.4],
            endY: [0.6, 0.8],
            maxYDeviation: 0.2
          }
        }
      } as Record<string, StrokePattern>,
      particles: [] as Particle[],
      isAnimating: false,
      bgMusic: null,
      soundEffects: {
        correct: '/static/sounds/correct.mp3',
        wrong: '/static/sounds/wrong.mp3',
        complete: '/static/sounds/complete.mp3'
      },
      canvasWidth: 0,
      canvasHeight: 0,
      isDrawing: false,
      lastX: 0,
      lastY: 0,
    }
  },
  computed: {
    currentLevelData() {
      return LEVELS[this.currentLevel - 1];
    }
  },
  watch: {
    currentLevel: {
      immediate: true,
      handler(newLevel) {
        const levelData = LEVELS[newLevel - 1];
        if (levelData) {
          this.currentStroke = {
            name: levelData.name,
            demoGif: levelData.demoGif,
            points: []
          };
        }
      }
    }
  },
  mounted() {
    setTimeout(() => {
      this.initCanvas();
    }, 100);
  },
  methods: {
    initCanvas() {
      const canvas = document.querySelector('#writeCanvas') as HTMLCanvasElement;
      if (!canvas) return;

      const dpr = window.devicePixelRatio || 1;
      const rect = canvas.getBoundingClientRect();

      this.canvasWidth = rect.width;
      this.canvasHeight = rect.height;
      canvas.width = this.canvasWidth;
      canvas.height = this.canvasHeight;

      const ctx = canvas.getContext('2d');
      if (!ctx) return;
      this.ctx = ctx;

      ctx.strokeStyle = '#FF9999';
      ctx.lineWidth = 4;
      ctx.lineCap = 'round';
      ctx.lineJoin = 'round';
    },

    getCanvasPoint(clientX: number, clientY: number) {
      const canvas = document.querySelector('#writeCanvas') as HTMLCanvasElement;
      if (!canvas) return { x: 0, y: 0 };

      const rect = canvas.getBoundingClientRect();
      const scaleX = canvas.width / rect.width;
      const scaleY = canvas.height / rect.height;

      return {
        x: (clientX - rect.left - window.pageXOffset) * scaleX,
        y: (clientY - rect.top - window.pageYOffset) * scaleY
      };
    },

    handleMouseDown(e: MouseEvent) {
      this.isDrawing = true;
      const rect = (e.target as HTMLCanvasElement).getBoundingClientRect();
      const x = e.clientX - rect.left;
      const y = e.clientY - rect.top;
      
      if (this.ctx) {
        this.ctx.beginPath();
        this.ctx.moveTo(x, y);
        this.lastX = x;
        this.lastY = y;
        this.currentStroke.points.push({ x, y });
      }
    },

    handleMouseMove(e: MouseEvent) {
      if (!this.isDrawing || !this.ctx) return;
      
      const rect = (e.target as HTMLCanvasElement).getBoundingClientRect();
      const x = e.clientX - rect.left;
      const y = e.clientY - rect.top;
      
      this.ctx.lineTo(x, y);
      this.ctx.stroke();
      
      this.lastX = x;
      this.lastY = y;
      this.currentStroke.points.push({ x, y });
    },

    handleMouseUp() {
      this.isDrawing = false;
      if (this.ctx) {
        this.ctx.closePath();
      }
    },

    handleTouchStart(e: TouchEvent) {
      e.preventDefault();
      const touch = e.touches[0];
      const rect = (e.target as HTMLCanvasElement).getBoundingClientRect();
      const x = touch.clientX - rect.left;
      const y = touch.clientY - rect.top;
      
      if (this.ctx) {
        this.ctx.beginPath();
        this.ctx.moveTo(x, y);
        this.lastX = x;
        this.lastY = y;
        this.currentStroke.points.push({ x, y });
      }
    },

    handleTouchMove(e: TouchEvent) {
      e.preventDefault();
      if (!this.ctx) return;
      
      const touch = e.touches[0];
      const rect = (e.target as HTMLCanvasElement).getBoundingClientRect();
      const x = touch.clientX - rect.left;
      const y = touch.clientY - rect.top;
      
      this.ctx.lineTo(x, y);
      this.ctx.stroke();
      
      this.lastX = x;
      this.lastY = y;
      this.currentStroke.points.push({ x, y });
    },

    handleTouchEnd(e: TouchEvent) {
      e.preventDefault();
      this.isDrawing = false;
      if (this.ctx) {
        this.ctx.closePath();
      }
    },

    showStrokeDemo() {
      this.showDemo = true;
      // 播放当前笔画的读音
      const levelData = LEVELS[this.currentLevel - 1];
      if (levelData) {
        this.playSound(levelData.sound);
      }
      setTimeout(() => {
        this.showDemo = false;
      }, 2000);
    },

    clearCanvas() {
      if (this.ctx) {
        this.ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
        this.currentStroke.points = [];
      }
    },

    checkStroke() {
      const points = this.currentStroke.points;
      if (points.length < 2) {
        uni.showToast({
          title: '请写一个字',
          icon: 'none'
        });
        return;
      }

      const levelData = LEVELS[this.currentLevel - 1];
      const pattern = this.strokePatterns[levelData.pattern];
      
      if (this.isStrokeValid(points, pattern.validRange)) {
        this.stars++;
        this.playSound('/static/sounds/correct.mp3');
        this.showReward();
        
        uni.showToast({
          title: '写得真棒！',
          icon: 'success'
        });

        // 延迟一下再进入下一关
        setTimeout(() => {
          if (this.currentLevel < LEVELS.length) {
            this.currentLevel++;
            this.clearCanvas();
          } else {
            uni.showToast({
              title: '恭喜完成所有关卡！',
              icon: 'success',
              duration: 2000
            });
          }
        }, 1500);
      } else {
        this.playSound('/static/sounds/wrong.mp3');
        uni.showToast({
          title: '再试一次吧',
          icon: 'none'
        });
        setTimeout(() => {
          this.clearCanvas();
        }, 1000);
      }
    },

    playSound(soundUrl: string) {
      const innerAudioContext = uni.createInnerAudioContext();
      innerAudioContext.src = soundUrl;
      innerAudioContext.autoplay = true;
      innerAudioContext.onError((res) => {
        console.error('音频播放失败：', res);
      });
    },

    showReward() {
      if (!this.ctx) return;
      
      // 使用简单的动画效果替代图片
      const centerX = this.canvasWidth / 2;
      const centerY = this.canvasHeight / 2;
      
      let angle = 0;
      let frames = 0;
      
      const drawStar = () => {
        if (!this.ctx) return;
        
        this.ctx.save();
        this.ctx.translate(centerX, centerY);
        this.ctx.rotate(angle);
        
        // 画一个星形
        this.ctx.beginPath();
        for (let i = 0; i < 5; i++) {
          const x = Math.cos((i * 4 * Math.PI) / 5) * 30;
          const y = Math.sin((i * 4 * Math.PI) / 5) * 30;
          if (i === 0) {
            this.ctx.moveTo(x, y);
          } else {
            this.ctx.lineTo(x, y);
          }
        }
        this.ctx.closePath();
        
        this.ctx.fillStyle = '#FFB6B6';
        this.ctx.fill();
        this.ctx.restore();
        
        angle += 0.1;
        frames++;
        
        if (frames < 30) {
          requestAnimationFrame(drawStar);
        } else {
          setTimeout(() => {
            this.clearCanvas();
          }, 500);
        }
      };
      
      drawStar();
    },

    createParticles(x: number, y: number) {
      for (let i = 0; i < 3; i++) {
        this.particles.push({
          x,
          y,
          size: Math.random() * 3 + 2,
          speedX: (Math.random() - 0.5) * 4,
          speedY: (Math.random() - 0.5) * 4,
          life: 1
        });
      }
      this.animateParticles();
    },

    animateParticles() {
      if (this.isAnimating || !this.particleCanvasCtx) return;
      this.isAnimating = true;

      const animate = () => {
        if (this.particles.length === 0 || !this.particleCanvasCtx) {
          this.isAnimating = false;
          return;
        }

        this.particleCanvasCtx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);

        this.particles.forEach((particle, index) => {
          particle.x += particle.speedX;
          particle.y += particle.speedY;
          particle.life -= 0.02;
          
          if (particle.life <= 0) {
            this.particles.splice(index, 1);
            return;
          }

          this.particleCanvasCtx?.beginPath();
          this.particleCanvasCtx?.arc(particle.x, particle.y, particle.size, 0, Math.PI * 2);
          this.particleCanvasCtx.fillStyle = `rgba(255, 182, 182, ${particle.life})`;
          this.particleCanvasCtx?.fill();
        });

        requestAnimationFrame(animate);
      };

      animate();
    },

    isStrokeValid(points: Point[], validRange: StrokePattern['validRange']): boolean {
      if (points.length < 2) return false;

      const start = points[0];
      const end = points[points.length - 1];
      if (!start || !end) return false;

      const relativeStart = {
        x: start.x / this.canvasWidth,
        y: start.y / this.canvasHeight
      };
      
      const relativeEnd = {
        x: end.x / this.canvasWidth,
        y: end.y / this.canvasHeight
      };

      return (
        relativeStart.x >= validRange.startX[0] &&
        relativeStart.x <= validRange.startX[1] &&
        relativeStart.y >= validRange.startY[0] &&
        relativeStart.y <= validRange.startY[1] &&
        relativeEnd.x >= validRange.endX[0] &&
        relativeEnd.x <= validRange.endX[1] &&
        relativeEnd.y >= validRange.endY[0] &&
        relativeEnd.y <= validRange.endY[1]
      );
    }
  }
}
</script>

<style>
.stroke-page {
  background-color: #FFF9F9;
  min-height: 100vh;
  padding: 20rpx;
}

.progress-bar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 20rpx;
}

.stars {
  display: flex;
  gap: 10rpx;
}

.star-icon {
  width: 40rpx;
  height: 40rpx;
}

.level-text {
  font-size: 32rpx;
  color: #FF9999;
}

.level-title {
  text-align: center;
  font-size: 36rpx;
  color: #FF9999;
  margin: 20rpx 0;
}

.writing-area {
  margin: 20rpx auto;
  width: 600rpx;
  height: 600rpx;
  border: 4rpx dashed #FFB6B6;
  border-radius: 20rpx;
  position: relative;
  background-color: rgba(255, 255, 255, 0.8);
}

.guide-lines {
  position: absolute;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

.guide-line {
  position: absolute;
  background-color: rgba(255, 182, 182, 0.3);
}

.guide-line.horizontal {
  width: 100%;
  height: 2rpx;
  top: 50%;
  transform: translateY(-50%);
}

.guide-line.vertical {
  width: 2rpx;
  height: 100%;
  left: 50%;
  transform: translateX(-50%);
}

.demo-stroke {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: rgba(255, 255, 255, 0.9);
  z-index: 4;
}

.bottom-actions {
  display: flex;
  justify-content: space-around;
  margin-top: 40rpx;
}

.action-btn {
  padding: 20rpx 40rpx;
  border-radius: 30rpx;
  font-size: 28rpx;
}

.demo-btn {
  background-color: #FFB6B6;
  color: white;
}

.clear-btn {
  background-color: #B6E3FF;
  color: white;
}

.submit-btn {
  background-color: #B6FFB6;
  color: white;
}

.write-canvas {
  width: 100% !important;
  height: 100% !important;
  position: absolute;
  left: 0;
  top: 0;
  background-color: rgba(255, 255, 255, 0.5);
  z-index: 1;
  cursor: crosshair;
  touch-action: none;
  -webkit-user-select: none;
  user-select: none;
  display: block;
}

.particle-canvas {
  width: 100%;
  height: 100%;
  position: absolute;
  left: 0;
  top: 0;
  pointer-events: none;
  z-index: 2;
}

.reward-animation {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 999;
}

.demo-line {
  position: absolute;
  background-color: #FF9999;
  border-radius: 4rpx;
}

/* 横的动画 */
.demo-line.横 {
  top: 50%;
  left: 20%;
  height: 8rpx;
  width: 0;
  animation: drawHorizontal 2s ease-in-out forwards;
}

/* 竖的动画 */
.demo-line.竖 {
  left: 50%;
  top: 20%;
  width: 8rpx;
  height: 0;
  animation: drawVertical 2s ease-in-out forwards;
}

/* 撇的动画 */
.demo-line.撇 {
  left: 70%;
  top: 30%;
  width: 8rpx;
  height: 0;
  transform: rotate(-45deg);
  transform-origin: top left;
  animation: drawLeftSlash 2s ease-in-out forwards;
}

@keyframes drawHorizontal {
  0% { width: 0; }
  100% { width: 60%; }
}

@keyframes drawVertical {
  0% { height: 0; }
  100% { height: 60%; }
}

@keyframes drawLeftSlash {
  0% { height: 0; }
  100% { height: 80%; }
}

/* 添加星星动画样式 */
@keyframes spin {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}

.page-title {
  text-align: center;
  font-size: 40rpx;
  color: #333;
  font-weight: bold;
  margin: 20rpx 0;
}

.current-char-container {
  text-align: center;
  margin: 30rpx 0;
  position: relative;
  z-index: 5;
}

.current-char-text {
  display: inline-block;
  font-size: 80rpx;
  color: #FF9999;
  font-weight: bold;
  background: #FFF;
  width: 140rpx;
  height: 140rpx;
  line-height: 140rpx;
  text-align: center;
  border-radius: 50%;
  box-shadow: 0 4rpx 20rpx rgba(255, 153, 153, 0.3);
}
</style> 